package gun0912.tedbottompicker;

import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.alexvasilkov.gestures.animation.ViewPosition;
import com.bumptech.glide.Glide;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.yalantis.ucrop.UCrop;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;

import androidx.annotation.ColorRes;
import androidx.annotation.DimenRes;
import androidx.annotation.DrawableRes;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.widget.ListPopupWindow;
import androidx.appcompat.widget.Toolbar;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentTransaction;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.CursorLoader;
import androidx.loader.content.Loader;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SimpleItemAnimator;
import gun0912.tedbottompicker.adapter.FolderAdapter;
import gun0912.tedbottompicker.adapter.GalleryAdapter;
import gun0912.tedbottompicker.entity.Folder;
import gun0912.tedbottompicker.util.ImageUtils;
import gun0912.tedbottompicker.util.RealPathUtil;
import gun0912.tedbottompicker.util.ToastMaster;
import gun0912.tedbottompicker.util.UCropUtils;
import gun0912.tedbottompicker.util.Utils;
import gun0912.tedbottompicker.util.ViewUtils;

public class PhotoPicker extends BottomSheetDialogFragment {

    public static final String TAG = "TedBottomPicker";
    static final int REQ_CODE_CAMERA = 1;
    static final int REQ_CODE_GALLERY = 2;
    static final int REQ_CODE_CROP = 3;
    private static final int REQ_CODE_PREVIEW = 4;
    static final String EXTRA_CAMERA_IMAGE_URI = "camera_image_uri";
    static final String EXTRA_CAMERA_SELECTED_IMAGE_URI = "camera_selected_image_uri";
    public static final int MAX_PREVIEW_COUNT = 200;
    public Builder builder;
    GalleryAdapter imageGalleryAdapter;
    Toolbar        view_title_container;
    TextView       tv_title;
    Button         btn_preview;
    Button         btn_done;

    FrameLayout selected_photos_container_frame;
    HorizontalScrollView hsv_selected_photos;
    LinearLayout selected_photos_container;

    TextView selected_photos_empty;
    View contentView;


    private ListPopupWindow mFolderPopupWindow;

    private TextView     mCategoryText;
    private View         mPopupAnchorView;
    private Uri          cameraImageUri;
    private RecyclerView rc_gallery;
    private boolean      isProportion;


    private BottomSheetBehavior.BottomSheetCallback mBottomSheetBehaviorCallback = new BottomSheetBehavior.BottomSheetCallback() {


        @Override
        public void onStateChanged(@NonNull View bottomSheet, int newState) {
            Log.d(TAG, "onStateChanged() newState: " + newState);
            if (newState == BottomSheetBehavior.STATE_HIDDEN) {
                dismissAllowingStateLoss();
            }
            if(space!=null&&space.getMeasuredHeight()>0) {
                if (newState == BottomSheetBehavior.STATE_EXPANDED || newState == BottomSheetBehavior.STATE_COLLAPSED) {
                    space.setBackgroundResource(R.drawable.ucrop_bg_toolbar);
                } else {
                    space.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
                }
            }
        }

        @Override
        public void onSlide(@NonNull View bottomSheet, float slideOffset) {
            Log.d(TAG, "onSlide() slideOffset: " + slideOffset);
        }
    };
    private FolderAdapter mFolderAdapter;
    private String previewImagePath;
    private File tempCutFile;
    private View root_view;
    private File cameraImagePath;
    private ArrayList<Uri> tempUriList;
    private View space;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setupSavedInstanceState(savedInstanceState);

        //  setRetainInstance(true);
    }

    private void setupSavedInstanceState(Bundle savedInstanceState) {


        if (savedInstanceState == null) {
            cameraImageUri = builder.selectedUri;
            tempUriList = builder.selectedUriList;
        } else {
            cameraImageUri = savedInstanceState.getParcelable(EXTRA_CAMERA_IMAGE_URI);
            tempUriList = savedInstanceState.getParcelableArrayList(EXTRA_CAMERA_SELECTED_IMAGE_URI);
        }


    }


    @Override
    public void onSaveInstanceState(Bundle outState) {
        outState.putParcelable(EXTRA_CAMERA_IMAGE_URI, cameraImageUri);
        outState.putParcelableArrayList(EXTRA_CAMERA_SELECTED_IMAGE_URI, tempUriList);
        super.onSaveInstanceState(outState);

    }

    public void show() {

        FragmentTransaction ft = builder.context.getSupportFragmentManager().beginTransaction();
        ft.add(this, getTag());
        ft.commitAllowingStateLoss();
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new BottomSheetDialog(getContext(), R.style.PhotoPickerDialogTheme);
    }

    @Override
    public void onViewCreated(View contentView, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(contentView, savedInstanceState);


    }

    @TargetApi(19)
    protected void setTranslucentStatus(boolean on) {
        if (!(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)) return;
        Window win = getDialog().getWindow();
        WindowManager.LayoutParams winParams = win.getAttributes();
        final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
        if (on) {
            winParams.flags |= bits;
        } else {
            winParams.flags &= ~bits;
        }
        win.setAttributes(winParams);
    }

    @SuppressLint("RestrictedApi")
    @Override
    public void setupDialog(Dialog dialog, int style) {
        super.setupDialog(dialog, style);
        contentView = View.inflate(getContext(), R.layout.tedbottompicker_content_view, null);
        dialog.setContentView(contentView);
        CoordinatorLayout.LayoutParams layoutParams =
                (CoordinatorLayout.LayoutParams) ((View) contentView.getParent()).getLayoutParams();
        CoordinatorLayout.Behavior behavior = layoutParams.getBehavior();
        if (behavior != null && behavior instanceof BottomSheetBehavior) {
            ((BottomSheetBehavior) behavior).setBottomSheetCallback(mBottomSheetBehaviorCallback);
            if (builder != null && builder.peekHeight > 0) {
                ((BottomSheetBehavior) behavior).setPeekHeight(builder.peekHeight);
            }
            //        if (isMultiSelect()) {
            ((BottomSheetBehavior) behavior).setState(BottomSheetBehavior.STATE_EXPANDED);
//        }
        }
        if (builder == null) {
            builder = new Builder(getActivity());
        }
        setTranslucentStatus(true);
        initView(contentView);
//        ViewUtils.paddingToStatusBar(space);
        setTitle();
        setRecyclerView();
        setSelectionView();


        if (builder.onImageSelectedListener != null && cameraImageUri != null) {
            addUri(cameraImageUri);
        }
        updateCurrentSelectedText();
        setDoneButton();
        setPreviewButton();
        checkConfirmMode();
        mCategoryText.setText(R.string.mis_recent_photo);
        mCategoryText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if (mFolderPopupWindow == null) {
                    createPopupFolderList();
                }

                if (mFolderPopupWindow.isShowing()) {
                    mFolderPopupWindow.dismiss();
                } else {
                    mFolderPopupWindow.show();
                    int index = mFolderAdapter.getSelectIndex();
                    index = index == 0 ? index : index - 1;
                    mFolderPopupWindow.getListView().setSelection(index);
                }
            }
        });
        mFolderAdapter = new FolderAdapter(getActivity());
        getActivity().getSupportLoaderManager().restartLoader(LOADER_ALL, null, mLoaderCallback);
    }

    private void createPopupFolderList() {
        int width = ViewUtils.getDisplayWidth();
        int height = (int) (ViewUtils.getDisplayHeight() * (4.8f / 8.0f));
        mFolderPopupWindow = new ListPopupWindow(getActivity());
        mFolderPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.WHITE));
        mFolderPopupWindow.setAdapter(mFolderAdapter);
        mFolderPopupWindow.setContentWidth(width);
        mFolderPopupWindow.setWidth(width);
        mFolderPopupWindow.setHeight(height);
        mFolderPopupWindow.setAnchorView(mPopupAnchorView);
        mFolderPopupWindow.setModal(true);
        mFolderPopupWindow.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {

                mFolderAdapter.setSelectIndex(i);

                final int index = i;
                final AdapterView v = adapterView;

                mFolderPopupWindow.dismiss();
                boolean dirChanged = true;
                if (index == 0) {
//                            getActivity().getSupportLoaderManager().restartLoader(LOADER_ALL, null, mLoaderCallback);
                    mCategoryText.setText(R.string.mis_recent_photo);
//                            if (showCamera()) {
//                                mImageAdapter.setShowCamera(true);
//                            } else {
//                                mImageAdapter.setShowCamera(false);
//                            }
                    if (builder.dirId != null) {
                        dirChanged = true;
                    }
                    builder.dirId = null;
                } else {
                    Folder folder = (Folder) v.getAdapter().getItem(index);
                    if (null != folder) {
//                                mImageAdapter.setData(folder.images);
                        mCategoryText.setText(folder.name);
//                                if (resultList != null && resultList.size() > 0) {
//                                    mImageAdapter.setDefaultSelected(resultList);
//                                }
                        if (builder.dirId != folder.id) {
                            dirChanged = true;
                        }
                        builder.dirId = folder.id;
                    }

//                            mImageAdapter.setShowCamera(false);
                }
                if (dirChanged) {
                    updateAdapter();
                }

            }
        });
    }

    // loaders
    private static final int                      LOADER_ALL      = 0;
    private static final int                      LOADER_CATEGORY = 1;
    private LoaderManager.LoaderCallbacks<Cursor> mLoaderCallback = new LoaderManager.LoaderCallbacks<Cursor>() {
        private final String[] IMAGE_PROJECTION = {
                "count(1) length",
                MediaStore.Images.Media.BUCKET_ID,
                MediaStore.Images.Media.DATA,
                MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
                MediaStore.Images.Media.DISPLAY_NAME,
                MediaStore.Images.Media.DATE_ADDED,
                MediaStore.Images.Media.MIME_TYPE,
                MediaStore.Images.Media.SIZE,
                MediaStore.Images.Media._ID};

        @Override
        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
            return new CursorLoader(getActivity(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION,
                    "1=1) GROUP BY " + MediaStore.Images.Media.BUCKET_ID + " -- (", null, MediaStore.Images.Media.BUCKET_DISPLAY_NAME
                    + " ASC," + MediaStore.Images.Media.DATE_MODIFIED + " DESC");
        }


        @Override
        public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
            if (!isAdded())
                return;
            ArrayList<Folder> resultFolder = new ArrayList<>();
            if (cursor != null && cursor.getCount() > 0) {
                cursor.moveToPosition(-1);
                while (cursor.moveToNext()) {
                    int id = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID));
                    String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
                    Folder dir = new Folder();
                    dir.id = String.valueOf(id);
                    dir.name = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME));
                    String dirPath;
                    int index = path.lastIndexOf('/');
                    if (index > 0) {
                        dirPath = path.substring(0, index);
                    } else {
                        dirPath = path;
                    }
                    dir.cover = path;
                    dir.path = dirPath;
                    dir.size = cursor.getInt(cursor.getColumnIndex("length"));
                    resultFolder.add(dir);
                }

                try
                {
                    //4.0以上的版本会自动关闭 (4.0--14;; 4.0.3--15)
                    if(Integer.parseInt(Build.VERSION.SDK) < 14)
                    {
                        cursor.close();
                    }
                }catch(Exception e)
                {

                }
//                cursor.close();

                mFolderAdapter.setData(resultFolder);
                mFolderAdapter.setPreviewImagePath(previewImagePath);
            }
        }

        @Override
        public void onLoaderReset(Loader<Cursor> loader) {

        }
    };

    private void setSelectionView() {

        if (builder.emptySelectionText != null) {
            selected_photos_empty.setText(builder.emptySelectionText);
        }


    }

    private void setDoneButton() {

        if (builder.completeButtonText != null) {
            btn_done.setText(builder.completeButtonText);
        }

        btn_done.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                onMultiSelectComplete();


            }
        });
    }

    private void setPreviewButton() {

        if (builder.completeButtonText != null) {
            btn_done.setText(builder.completeButtonText);
        }

        btn_preview.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if (!imageGalleryAdapter.hasSelectedUris()) {
                    ToastMaster.shortToast(getString(R.string.preview_photos_not_pick));
                    return;
                }

                startPreview(imageGalleryAdapter.getSelectedUriList().get(imageGalleryAdapter.getSelectedUriList().size() - 1));
            }
        });
    }


    private ArrayList<String> toUrls() {
        ArrayList<String> urls = new ArrayList<>();
        for (int i = imageGalleryAdapter.getSelectedUriList().size() - 1; i >= 0; i--) {
            Uri uri = imageGalleryAdapter.getSelectedUriList().get(i);
            urls.add(uri.toString());
        }
        return urls;
    }

    private void onMultiSelectComplete() {

        if (imageGalleryAdapter.getSelectedUriList().size() < builder.selectMinCount) {
            String message;
            if (builder.selectMinCountErrorText != null) {
                message = builder.selectMinCountErrorText;
            } else {
                message = String.format(getResources().getString(R.string.select_min_count), builder.selectMinCount);
            }

            Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show();
            return;
        }

        if (isMultiSelect()) {
            ArrayList<String> imageList = compressUriList(imageGalleryAdapter.getSelectedUriList());
            builder.onMultiImageSelectedListener.onImagesSelected(new Pair<ArrayList<Uri>, ArrayList<String>>(imageGalleryAdapter.getSelectedUriList(), imageList));
        } else {
            String compressPath = imageGalleryAdapter.getSelectedUriList().size() > 0 ? compressUri(imageGalleryAdapter.getSelectedUriList().get(0)) : null;
            Uri uri = imageGalleryAdapter.getSelectedUriList().size() > 0 ? imageGalleryAdapter.getSelectedUriList().get(0) : null;
            builder.onImageSelectedListener.onImageSelected(new Pair<Uri, String>(uri, compressPath));
        }
        dismissAllowingStateLoss();
    }


    private void checkConfirmMode() {
        if (!builder.needConfirm || !builder.showGalleryPreview) {
//            btn_done.setVisibility(View.GONE);
            selected_photos_container_frame.setVisibility(View.GONE);
        }

    }

    private void initView(View contentView) {
//        space = contentView.findViewById(R.id.space);
        view_title_container = (Toolbar) contentView.findViewById(R.id.view_title_container);
        view_title_container.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
            }
        });
        tv_title = (TextView) contentView.findViewById(R.id.tv_title);
        rc_gallery = (RecyclerView) contentView.findViewById(R.id.rc_gallery);
        root_view = contentView.findViewById(R.id.root_view);
        root_view.setMinimumHeight(ViewUtils.getDisplayHeight());
        btn_preview = (Button) contentView.findViewById(R.id.btn_preview);
        btn_done = (Button) contentView.findViewById(R.id.btn_done);

        selected_photos_container_frame = (FrameLayout) contentView.findViewById(R.id.selected_photos_container_frame);
        hsv_selected_photos = (HorizontalScrollView) contentView.findViewById(R.id.hsv_selected_photos);
        selected_photos_container = (LinearLayout) contentView.findViewById(R.id.selected_photos_container);
        selected_photos_empty = (TextView) contentView.findViewById(R.id.selected_photos_empty);
        mPopupAnchorView = contentView.findViewById(R.id.footer);
        mCategoryText = (TextView) contentView.findViewById(R.id.category_btn);
        mCategoryText.setText(R.string.mis_recent_photo);
    }

    private void setRecyclerView() {

        GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), 3);
        rc_gallery.setLayoutManager(gridLayoutManager);
        rc_gallery.addItemDecoration(new GridSpacingItemDecoration(gridLayoutManager.getSpanCount(), builder.spacing, false));
        updateAdapter();
    }

    private void updateAdapter() {
        if (tempUriList == null) {
            tempUriList = new ArrayList<>();
        }
        if (builder.selectedUriList == null) {
            builder.selectedUriList = new ArrayList<>();
        }
        imageGalleryAdapter = new GalleryAdapter(
                getActivity(), builder.selectedUriList, tempUriList
                , builder);
        rc_gallery.setAdapter(imageGalleryAdapter);
        ((SimpleItemAnimator) rc_gallery.getItemAnimator()).setSupportsChangeAnimations(false);
        int startPos = getStartPos();
        if (imageGalleryAdapter.getItemCount() > 1) {
            previewImagePath = Utils.getPathFromUri(getActivity(), imageGalleryAdapter.getItem(startPos).getImageUri());
        }
        imageGalleryAdapter.setOnItemClickListener(new GalleryAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {

                GalleryAdapter.PickerTile pickerTile = imageGalleryAdapter.getItem(position);

                switch (pickerTile.getTileType()) {
                    case GalleryAdapter.PickerTile.CAMERA:
                        startCameraIntent();
                        break;
                    case GalleryAdapter.PickerTile.GALLERY:
                        startGalleryIntent();
                        break;
                    case GalleryAdapter.PickerTile.IMAGE:
                        complete(pickerTile.getImageUri());

                        break;

                    default:
                        errorMessage();
                }

            }
        });
    }

    private int getStartPos() {
        int startPos = 0;
        if (builder.showCamera) {
            startPos++;
        }
        if (builder.showGallery) {
            startPos++;
        }
        return startPos;
    }

    private void complete(final Uri uri) {
        Log.d(TAG, "selected uri: " + uri.toString());

        if (!builder.needConfirm && !isMultiSelect()) {
            if (builder.onImageSelectedListener != null) {
                if (builder.needCrop) {
                    crop(uri);
                } else {
                    String compressed = compressUri(uri);
                    builder.onImageSelectedListener.onImageSelected(new Pair<Uri, String>(uri, compressed));
                    dismissAllowingStateLoss();
                }
            }

        } else {
            if (imageGalleryAdapter.getSelectedUriList().contains(uri)) {
                removeImage(uri);
            } else {
                if (!isMultiSelect()) {
                    clear();
                }
                addUri(uri);
            }
            updateCurrentSelectedText();
        }

    }

    public void crop(Uri uri) {
        tempCutFile = Utils.newTempFile();
        if (builder.isProportion)
            UCropUtils.start(this, uri, Uri.fromFile(tempCutFile), builder.cropStatusColor, tv_title.getCurrentTextColor(), 1);
        else
            UCropUtils.start(this, uri, Uri.fromFile(tempCutFile), builder.cropStatusColor, tv_title.getCurrentTextColor());


    }


    private static Context mContext;

    private String compressUri(Uri uri) {
        String path = Utils.getPathFromUri(mContext, uri);
        return ImageUtils.compressNoLargePhoto(mContext, new File(path));
    }

    private ArrayList<String> compressUriList(ArrayList<Uri> selectedUriList) {
        ArrayList<String> imageList = new ArrayList<>();
        for (Uri uri : selectedUriList) {
            imageList.add(compressUri(uri));
        }
        return imageList;
    }

    private void clear() {
        ListIterator<Uri> iterator = imageGalleryAdapter.getSelectedUriList().listIterator();
        while (iterator.hasNext()) {
            removeImage(iterator.next());
        }

    }

    private boolean addUri(final Uri uri) {


        if (imageGalleryAdapter.getSelectedUriList().size() == builder.selectMaxCount) {
            String message;
            if (builder.selectMaxCountErrorText != null) {
                message = builder.selectMaxCountErrorText;
            } else {
                message = String.format(getResources().getString(R.string.select_max_count), builder.selectMaxCount);
            }

            Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show();
            return false;
        }

        imageGalleryAdapter.addSelectedUri(uri);
        addToPreviewGallery(uri);
        updateSelectedView();
        return true;

    }

    private void addToPreviewGallery(final Uri uri) {
        if (builder.showGalleryPreview) {
            final View rootView = LayoutInflater.from(getActivity()).inflate(R.layout.tedbottompicker_selected_item, null);
            ImageView thumbnail = (ImageView) rootView.findViewById(R.id.selected_photo);
            ImageView iv_close = (ImageView) rootView.findViewById(R.id.iv_close);
            rootView.setTag(uri);
            thumbnail.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    startPreview(uri);
                }
            });
            selected_photos_container.addView(rootView, 0);


            int px = (int) getResources().getDimension(R.dimen.tedbottompicker_selected_image_height);
            thumbnail.setLayoutParams(new FrameLayout.LayoutParams(px, px));

            if (builder.imageProvider == null) {
                Glide.with(getActivity())
                        .load(uri)
                        .thumbnail(0.1f)
                        .into(thumbnail);
            } else {
                builder.imageProvider.onProvideImage(thumbnail, uri);
            }


            if (builder.deSelectIconDrawable != null) {
                iv_close.setImageDrawable(builder.deSelectIconDrawable);
            }

            iv_close.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    removeImage(uri);
                    updateCurrentSelectedText();
                }
            });
        }
    }

    private void removeFromPreviewGallery(Uri uri) {
        if (builder.showGalleryPreview) {
            for (int i = 0; i < selected_photos_container.getChildCount(); i++) {
                View childView = selected_photos_container.getChildAt(i);
                if (childView.getTag().equals(uri)) {
                    selected_photos_container.removeViewAt(i);
                    break;
                }
            }
        }
    }

    private void startPreview(Uri uri) {
        Intent intent = new Intent();
        intent.setClassName(builder.context.getPackageName(), builder.context.getPackageName() + ".ui.preview.PhotoPagerActivity");
        ArrayList<String> urls = toUrls();
        intent.putExtra("photoUrls", urls);
        intent.putExtra("checkable", true);
        intent.putExtra("maxCheckCount", builder.selectMaxCount);
        int position = urls.indexOf(uri.toString());
        intent.putExtra("position", position);
        if (builder.showGalleryPreview) {
            ArrayList<String> viewPositions = new ArrayList<>();
            int rightEdge = ViewUtils.getDisplayWidth();
            int firstVisibleViewPos = -1;
            for (int i = 0; i < selected_photos_container.getChildCount(); i++) {
                View child = selected_photos_container.getChildAt(i);
                ViewPosition viewPosition = ViewPosition.from(child);
                Rect frame = viewPosition.view;
                if ((frame.left < rightEdge && frame.right > 0) || (frame.left < rightEdge && frame.right > 0)) {
                    viewPositions.add(viewPosition.pack());
                    if (firstVisibleViewPos == -1) {
                        firstVisibleViewPos = i;
                    }
                }
            }
            intent.putExtra("extra_view_positions", viewPositions);
            intent.putExtra("extra_first_view_position", firstVisibleViewPos);
        }
        intent.putExtra("hide_status_bar", false);
        startActivityForResult(intent, REQ_CODE_PREVIEW);
    }

    private void updateCurrentSelectedText() {
        if (isMultiSelect()) {
            btn_preview.setVisibility(View.VISIBLE);
            if (imageGalleryAdapter.getSelectedUriList().size() == 0) {
                btn_preview.setEnabled(false);
                btn_preview.setText(R.string.preview);
            } else {
                btn_preview.setEnabled(true);
                String current = String.format(getResources().getString(R.string.current_selected_count), imageGalleryAdapter.getSelectedUriList().size(), builder.selectMaxCount);
                btn_preview.setText(current);
            }
        }
    }

    private void removeImage(Uri uri) {

        imageGalleryAdapter.removeSelectedUri(uri);
        removeFromPreviewGallery(uri);
        updateSelectedView();
    }

    private void updateSelectedView() {

        if (imageGalleryAdapter.getSelectedUriList().size() == 0) {
            selected_photos_empty.setVisibility(View.VISIBLE);
            selected_photos_container.setVisibility(View.GONE);
        } else {
            selected_photos_empty.setVisibility(View.GONE);
            selected_photos_container.setVisibility(View.VISIBLE);
        }

    }

    private void startCameraIntent() {
        cameraImagePath = getImageFile();
        Utils.takePhoto(this, REQ_CODE_CAMERA, cameraImagePath);

    }

    private static final String CAMERA_IMAGE_FILE_NAME = "_temp.jpg";

    private File getImageFile() {


        File imageFile = Utils.newTempFile();
        cameraImageUri = Uri.fromFile(imageFile);
        return imageFile;
    }

    private File getVideoFile() {
        // Create an image file name
        File videoFile = null;
        try {
            String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).format(new Date());
            String imageFileName = "VIDEO_" + timeStamp + "_";
            File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);

            if (!storageDir.exists())
                storageDir.mkdirs();

            videoFile = File.createTempFile(
                    imageFileName,  /* prefix */
                    ".mp4",         /* suffix */
                    storageDir      /* directory */
            );


            // Save a file: path for use with ACTION_VIEW intents
            cameraImageUri = Uri.fromFile(videoFile);
        } catch (IOException e) {
            e.printStackTrace();
            errorMessage("Could not create imageFile for camera");
        }


        return videoFile;
    }

    private void errorMessage(String message) {
        String errorMessage = message == null ? "Something wrong." : message;

        if (builder.onErrorListener == null) {
            Toast.makeText(getActivity(), errorMessage, Toast.LENGTH_SHORT).show();
        } else {
            builder.onErrorListener.onError(errorMessage);
        }
    }

    private void startGalleryIntent() {
        Intent galleryIntent;
        Uri uri;
        if (builder.mediaType == Builder.MediaType.IMAGE) {
            galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            galleryIntent.setType("image/*");
        } else {
            galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
            galleryIntent.setType("video/*");

        }

        if (galleryIntent.resolveActivity(getActivity().getPackageManager()) == null) {
            errorMessage("This Application do not have Gallery Application");
            return;
        }

        startActivityForResult(galleryIntent, REQ_CODE_GALLERY);

    }

    private void errorMessage() {
        errorMessage(null);
    }

    private void setTitle() {

        if (!builder.needConfirm) {
//            btn_preview.setVisibility(View.GONE);

//            if (!isMultiSelect()) {
//            view_title_container.setVisibility(View.GONE);
            btn_done.setVisibility(View.GONE);
            btn_preview.setVisibility(View.GONE);


//            }

        }

        if (!TextUtils.isEmpty(builder.title)) {
            tv_title.setText(builder.title);
        }

        if (builder.titleBackgroundResId > 0) {
            view_title_container.setBackgroundResource(builder.titleBackgroundResId);
        }

    }

    private boolean isMultiSelect() {
        return builder.onMultiImageSelectedListener != null;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {


            switch (requestCode) {
                case REQ_CODE_GALLERY:
                    onActivityResultGallery(data);
                    break;
                case REQ_CODE_CAMERA:
                    onActivityResultCamera(cameraImageUri);
                    break;
                case UCrop.REQUEST_CROP:
                    onActivityResultCrop(data);
                    break;
                case REQ_CODE_PREVIEW:
                    onActivityResultPreview(data);
                    break;
                default:
                    errorMessage();
            }


        }

    }

    private void onActivityResultPreview(Intent data) {
        ArrayList<String> currentUrls = data.getStringArrayListExtra("result");
        ListIterator<Uri> iterator = imageGalleryAdapter.getSelectedUriList().listIterator();
        List<Uri> changedUris = new ArrayList<>();
        while (iterator.hasNext()) {
            Uri uri = iterator.next();
            if (!currentUrls.contains(uri.toString())) {
                iterator.remove();
                changedUris.add(uri);
                removeFromPreviewGallery(uri);

            }
        }
        updateSelectedView();
        imageGalleryAdapter.notifyItemsChanged(changedUris);
        updateCurrentSelectedText();
    }


    private void onActivityResultCrop(Intent data) {
//        String imagePath = data.getExtras().getString("data");
        if (tempCutFile.exists() && tempCutFile.isFile() && tempCutFile.length() > 0) {
            if (builder.onImageSelectedListener != null) {
                builder.onImageSelectedListener.onImageSelected(new Pair<Uri, String>(Uri.fromFile(tempCutFile), tempCutFile.getAbsolutePath()));
                dismissAllowingStateLoss();
            }
        }
    }

    private void onActivityResultCamera(final Uri cameraImageUri) {
        imageGalleryAdapter.addTempUri(cameraImageUri);
        complete(cameraImageUri);
//        MediaScannerConnection.scanFile(getContext(), new String[]{cameraImageUri.getPath()}, new String[]{"image/jpeg"}, new MediaScannerConnection.MediaScannerConnectionClient() {
//            @Override
//            public void onMediaScannerConnected() {
//
//            }
//
//            @Override
//            public void onScanCompleted(String s, Uri uri) {
//                getActivity().runOnUiThread(new Runnable() {
//                    @Override
//                    public void run() {
//
//                    }
//                });
//
//            }
//        });
    }


    private void onActivityResultGallery(Intent data) {
        Uri temp = data.getData();

        if (temp == null) {
            errorMessage();
        }

        String realPath = RealPathUtil.getRealPath(getActivity(), temp);

        Uri selectedImageUri = null;
        try {
            selectedImageUri = Uri.fromFile(new File(realPath));
        } catch (Exception ex) {
            selectedImageUri = Uri.parse(realPath);
        }

        complete(selectedImageUri);

    }


    public interface OnMultiImageSelectedListener {
        void onImagesSelected(Pair<ArrayList<Uri>, ArrayList<String>> images);
    }

    public interface OnImageSelectedListener {
        void onImageSelected(Pair<Uri, String> imagePath);
    }


    public interface OnErrorListener {
        void onError(String message);
    }

    public interface ImageProvider {
        void onProvideImage(ImageView imageView, Uri imageUri);
    }

    public static class Builder {

        public FragmentActivity context;
        public int              previewMaxCount = Integer.MAX_VALUE;
        public Drawable         cameraTileDrawable;
        public Drawable         galleryTileDrawable;

        public Drawable deSelectIconDrawable;
        public Drawable selectedForegroundDrawable;

        public int spacing = 1;
        public OnImageSelectedListener onImageSelectedListener;
        public OnMultiImageSelectedListener onMultiImageSelectedListener;
        public OnErrorListener onErrorListener;
        public ImageProvider imageProvider;
        public boolean showCamera = true;
        public boolean showGallery = false;
        public int peekHeight = -1;
        public int cameraTileBackgroundResId = R.color.tedbottompicker_camera;
        public int galleryTileBackgroundResId = R.color.tedbottompicker_gallery;

        public String title;
        public boolean needConfirm = false;
        public int titleBackgroundResId;

        public int selectMaxCount = 9;
        public int selectMinCount = 1;


        public String completeButtonText;
        public String emptySelectionText;
        public String selectMaxCountErrorText;
        public String selectMinCountErrorText;
        public @MediaType
        int mediaType = MediaType.IMAGE;
        ArrayList<Uri> selectedUriList;
        Uri selectedUri;
        public String dirId;
        public boolean needCrop = false;
        public int cropStatusColor;
        public boolean showGalleryPreview = false;
        public boolean isProportion;



        public Builder(@NonNull FragmentActivity context) {

            this.context = context;

            setCameraTile(R.drawable.ic_camera);
            setGalleryTile(R.drawable.ic_gallery);
            setCropStatusColor(Utils.getColorPrimary(context));
            setSpacingResId(R.dimen.tedbottompicker_grid_layout_margin);
        }

        public Builder(@NonNull Fragment context) {

            this(context.getActivity());
        }

        public Builder setCameraTile(@DrawableRes int cameraTileResId) {
            setCameraTile(ContextCompat.getDrawable(context, cameraTileResId));
            return this;
        }

        public Builder setCameraTile(Drawable cameraTileDrawable) {
            this.cameraTileDrawable = cameraTileDrawable;
            return this;
        }

        public Builder setGalleryTile(@DrawableRes int galleryTileResId) {
            setGalleryTile(ContextCompat.getDrawable(context, galleryTileResId));
            return this;
        }

        public Builder setGalleryTile(Drawable galleryTileDrawable) {
            this.galleryTileDrawable = galleryTileDrawable;
            return this;
        }

        public Builder setSpacingResId(@DimenRes int dimenResId) {
            this.spacing = context.getResources().getDimensionPixelSize(dimenResId);
            return this;
        }

        public Builder setDeSelectIcon(@DrawableRes int deSelectIconResId) {
            setDeSelectIcon(ContextCompat.getDrawable(context, deSelectIconResId));
            return this;
        }

        public Builder setDeSelectIcon(Drawable deSelectIconDrawable) {
            this.deSelectIconDrawable = deSelectIconDrawable;
            return this;
        }

        public Builder setShowGalleryPreview(boolean showGalleryPreview) {
            this.showGalleryPreview = showGalleryPreview;
            return this;
        }

        public Builder setSelectedForeground(@DrawableRes int selectedForegroundResId) {
            setSelectedForeground(ContextCompat.getDrawable(context, selectedForegroundResId));
            return this;
        }

        public Builder setSelectedForeground(Drawable selectedForegroundDrawable) {
            this.selectedForegroundDrawable = selectedForegroundDrawable;
            return this;
        }

        public Builder setPreviewMaxCount(int previewMaxCount) {
            this.previewMaxCount = previewMaxCount;
            return this;
        }

        public Builder setSelectMaxCount(int selectMaxCount) {
            this.selectMaxCount = selectMaxCount;
            return this;
        }

        public Builder setCropStatusColor(int cropStatusColor) {
            this.cropStatusColor = cropStatusColor;
            return this;
        }

        public Builder setSelectMinCount(int selectMinCount) {
            this.selectMinCount = selectMinCount;
            return this;
        }

        public Builder setOnImageSelectedListener(OnImageSelectedListener onImageSelectedListener) {
            this.onImageSelectedListener = onImageSelectedListener;
            this.onMultiImageSelectedListener = null;
            return this;
        }


        public Builder setOnMultiImageSelectedListener(OnMultiImageSelectedListener onMultiImageSelectedListener) {
            this.onMultiImageSelectedListener = onMultiImageSelectedListener;
            this.onImageSelectedListener = null;
            return this;
        }

        public Builder setOnErrorListener(OnErrorListener onErrorListener) {
            this.onErrorListener = onErrorListener;
            return this;
        }

        public Builder showCamera() {
            this.showCamera = true;
            return this;
        }

        public Builder hideCamera() {
            this.showCamera = false;
            return this;
        }

        public Builder showGalleryTile(boolean showGallery) {
            this.showGallery = showGallery;
            return this;
        }

        public Builder setSpacing(int spacing) {
            this.spacing = spacing;
            return this;
        }

        public Builder setPeekHeight(int peekHeight) {
            this.peekHeight = peekHeight;
            return this;
        }

        public Builder setPeekHeightResId(@DimenRes int dimenResId) {
            this.peekHeight = context.getResources().getDimensionPixelSize(dimenResId);
            return this;
        }

        public Builder setCameraTileBackgroundResId(@ColorRes int colorResId) {
            this.cameraTileBackgroundResId = colorResId;
            return this;
        }

        public Builder setGalleryTileBackgroundResId(@ColorRes int colorResId) {
            this.galleryTileBackgroundResId = colorResId;
            return this;
        }

        public Builder setTitle(String title) {
            this.title = title;
            return this;
        }

        public Builder setTitle(@StringRes int stringResId) {
            this.title = context.getResources().getString(stringResId);
            return this;
        }

        public Builder setCompleteButtonText(String completeButtonText) {
            this.completeButtonText = completeButtonText;
            return this;
        }

        public Builder setCompleteButtonText(@StringRes int completeButtonResId) {
            this.completeButtonText = context.getResources().getString(completeButtonResId);
            return this;
        }

        public Builder setEmptySelectionText(String emptySelectionText) {
            this.emptySelectionText = emptySelectionText;
            return this;
        }

        public Builder setEmptySelectionText(@StringRes int emptySelectionResId) {
            this.emptySelectionText = context.getResources().getString(emptySelectionResId);
            return this;
        }

        public Builder setSelectMaxCountErrorText(String selectMaxCountErrorText) {
            this.selectMaxCountErrorText = selectMaxCountErrorText;
            return this;
        }

        public Builder setSelectMaxCountErrorText(@StringRes int selectMaxCountErrorResId) {
            this.selectMaxCountErrorText = context.getResources().getString(selectMaxCountErrorResId);
            return this;
        }

        public Builder setSelectMinCountErrorText(String selectMinCountErrorText) {
            this.selectMinCountErrorText = selectMinCountErrorText;
            return this;
        }

        public Builder setSelectMinCountErrorText(@StringRes int selectMinCountErrorResId) {
            this.selectMinCountErrorText = context.getResources().getString(selectMinCountErrorResId);
            return this;
        }

        public Builder setTitleBackgroundResId(@ColorRes int colorResId) {
            this.titleBackgroundResId = colorResId;
            return this;
        }

        public Builder setImageProvider(ImageProvider imageProvider) {
            this.imageProvider = imageProvider;
            return this;
        }

        public Builder setSelectedUriList(ArrayList<Uri> selectedUriList) {
            this.selectedUriList = selectedUriList;
            return this;
        }

        public Builder setSelectedUri(Uri selectedUri) {
            this.selectedUri = selectedUri;
            return this;
        }

        public Builder showVideoMedia() {
            this.mediaType = MediaType.VIDEO;
            return this;
        }

        public PhotoPicker create() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
                    && ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                throw new RuntimeException("Missing required WRITE_EXTERNAL_STORAGE permission. Did you remember to request it first?");
            }

            if (onImageSelectedListener == null && onMultiImageSelectedListener == null) {
                throw new RuntimeException("You have to use setOnImageSelectedListener() or setOnMultiImageSelectedListener() for receive selected Uri");
            }

            PhotoPicker customBottomSheetDialogFragment = new PhotoPicker();
            if (peekHeight == -1) {
                peekHeight = context.getResources().getDisplayMetrics().heightPixels;
            }
            if (onMultiImageSelectedListener != null) {
                needConfirm = true;
            }
            customBottomSheetDialogFragment.builder = this;
            return customBottomSheetDialogFragment;
        }

        public Builder setDirId(String dirId) {
            this.dirId = dirId;
            return this;
        }

        public Builder crop() {
            this.needCrop = true;
            return this;
        }

        public Builder crop(boolean isProportion) {
            this.needCrop = true;
            this.isProportion = isProportion;
            return this;
        }

        public Builder confirm() {
            this.needConfirm = true;
            return this;
        }

        @Retention(RetentionPolicy.SOURCE)
        @IntDef({MediaType.IMAGE, MediaType.VIDEO})
        public @interface MediaType {
            int IMAGE = 1;
            int VIDEO = 2;
        }


    }


}
